package codec

import (
	"bytes"
	"encoding/binary"
	"encoding/hex"
	"gitee.com/gcom/gbox/errors"
	"gitee.com/gcom/ths_socket/socks5"
	"strconv"
)

var ThsDelimiter = [...]byte{0xFD, 0xFD, 0xFD, 0xFD}

func ReadPkg(con socks5.BufferedConn, sessionType int32) (*DataPack, error) {
	var head = make([]byte, 12)
	_, err := con.ReadFull(head[:])
	if err != nil {
		return nil, err
	}
	if !bytes.Equal(head[:4], ThsDelimiter[:]) {
		return nil, errors.Newf("无效的数据包, %s", hex.EncodeToString(head[:]))
	}
	var ls = string(head[4:12])
	l, err := strconv.ParseInt(ls, 16, 32)
	if err != nil {
		return nil, errors.Newf("无效的数据包长度: %s", ls)
	}

	if l == 0 { // 心跳包，读取结尾的\0
		b, e := con.ReadByte()
		if e != nil {
			return nil, e
		}
		if b != 0x00 {
			return nil, errors.New("无效的心跳包")
		}
		return nil, nil
	}

	var data = make([]byte, 12+int(l)+1) // 1 byte for package end char(\n)
	body := data[12:]
	if _, err = con.ReadFull(body); err != nil {
		return nil, errors.Wrap(err, "读取body失败")
	}
	dp := DataPack{}
	dp.HeadLength = int32(binary.BigEndian.Uint16(body[0:2]))
	dp.PackageId = int32(binary.LittleEndian.Uint32(body[2:6]))
	dp.HeadType = int32(binary.LittleEndian.Uint32(body[6:10]))
	dp.PageId = int32(binary.LittleEndian.Uint16(body[10:12]))
	dp.DataLength = int32(binary.LittleEndian.Uint32(body[12:16]))
	dp.FrameId = int32(binary.LittleEndian.Uint32(body[16:20]))
	dp.TextLength = int32(binary.LittleEndian.Uint32(body[20:24]))
	dp.SessionType = sessionType

	if l >= 28 {
		dp.Body = body[28:]
	}
	copy(data[:12], head[:])
	dp.OriginData = data
	//var en = uint32(dp.EncryptType) & (uint32(0x0F) << 28)
	//var et EncType
	//switch en {
	//case uint32(1) << 28:
	//	et = EncDes
	//	break
	//case uint32(1) << 29:
	//	et = EncBigInt
	//	break
	//case uint32(7) << 28:
	//	et = EncAes
	//	break
	//default:
	//	et = EncPlain
	//}

	return &dp, nil
}
